#pragma once

#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <fstream>
#include "Logger.hpp"

static const std::string linesep = "\r\n";
static const std::string innersep1 = " ";
static const std::string innersep2 = ": ";
static const std::string webroot = "./wwwroot";
static const std::string defaulthome = "index.html";
static const std::string html_404 = "404.html";
static const std::string suffixsep = ".";

// 定制http协议！
class HttpRequest
{
private:
    std::string ReadOneLine(std::string & reqstr,bool * status)
    {
        auto pos=reqstr.find(linesep);
        if(pos==std::string::npos)
        {
            *status=false;
            return std::string();
        }
        *status=true;
        auto line=reqstr.substr(0,pos);
        reqstr.erase(0,pos+linesep.size());
        return line;
    }

    void ParseQeqLine(std::string &reqline)
    {
         // GET / HTTP/1.1 ->     std::string _method; std::string _uri; std::string _httpversion;
         std::stringstream ss(reqline);
         ss>>_method >> _uri >> _httpversion;
         // LOG(LogLevel::DEBUG) << "_method:" << _method;
        // LOG(LogLevel::DEBUG) << "_uri:" << _uri;
        // LOG(LogLevel::DEBUG) << "_httpversion:" << _httpversion;
    }
    void BuideKV(std::string &reqline,std::string* k,std::string* v)
    {
        auto pos=reqline.find(innersep2);
        if(pos==std::string::npos)
        {
            *k=*v=std::string();
            return;
        }
        *k=reqline.substr(0,pos);
        *v=reqline.substr(pos+innersep2.size());

    }
public:
    HttpRequest(){}
    void Serialize()
    {
        //不做，交给浏览器
    }

    //reqstr:是一个完整的请求
    bool Deserialize(std::string &reqstr)
    {
        bool status=true;
        std::string reqline=ReadOneLine(reqstr,&status);
        if(!status)
        return false;

        ParseQeqLine(reqline);

        while(true)
        {
            status=true;
            reqline=ReadOneLine(reqstr,&status);
            if(status && !reqline.empty())
            {
                std::string k,v;
                BuideKV(reqline,&k,&v);
                if(k.empty()||v.empty())
                    continue;;
                _req_headers.insert(std::make_pair(k,v));
            }
            else if(status)
            {
                _blank_line=linesep;
                break;
            }
            else{
                LOG(LogLevel::DEBUG) << "非法请求";
                // return false; // 暂时
                break;
            }
        }
        _req_body=reqstr;

        _path=webroot;
        if(_uri=="/")
        {
            _path+=_uri;
            _path+=defaulthome;
        }
        else 
        {
            _path+=_uri;
        }

        return true;
    }
    std::string Path()
    {
        return _path;
    }
    ~HttpRequest(){}  
private:
    std::string _method;
    std::string _uri;
    std::string _httpversion;
    std::unordered_map<std::string,std::string> _req_headers;
    std::string _blank_line;
    std::string _req_body;

    std::string _path;
};


class HttpRespond
{
private:

public:
    HttpRespond(){}
    void Serialize()
    {
      
    }

    bool Deserialize()
    {
      //交给浏览器
    }
     bool ReadContent(const std::string &path)
    {
        // 以二级制方式读取
        // 打开文件，二进制模式
        std::ifstream file(path, std::ios::binary);
        if (!file.is_open())
        {
            LOG(LogLevel::WARNING) << path << " 资源不存在!";
            return false;
        }

        // 定位到文件末尾获取文件大小
        file.seekg(0, std::ios::end);
        std::streampos fileSize = file.tellg(); // 获取文件大小
        file.seekg(0, std::ios::beg);

        // 创建足够大的字符串来保存数据
        _resp_body.resize(static_cast<size_t>(fileSize));

        // 读取文件内容到字符串
        file.read(&_resp_body[0], fileSize);
        file.close();

        return true;
    }
    
    ~HttpRespond(){} 
private:
        std::string _httpversion;
    int _code;
    std::string _desc;
    std::unordered_map<std::string, std::string> _resp_headers;
    std::string _blank_line;
    std::string _resp_body;
};

class Http
{
public: 
    Http(){}
    std::string HandlerRequest(std::string &requeststr)
    {
        HttpRequest req;
        if(req.Deserialize(requeststr))
        {
            std::string target = req.Path();
            HttpRespond resp;
        }


        return std::string();
    }
};